using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using Fadd.Globalization;

namespace Fadd.Validation
{
    /// <summary>
    /// Does validation using the current language.
    /// </summary>
    /// <remarks>
    /// This class is thread safe, meaning that you can have multiple threads using it at the same time.
    /// </remarks>
    public class LocalizedValidator
    {
        private readonly ILanguageNode _validatorLanguage;

        /// <summary>
        /// Initializes a new instance of the <see cref="LocalizedValidator"/> class.
        /// </summary>
        /// <param name="validationLanguage">Node with the validation language.</param>
        public LocalizedValidator(ILanguageNode validationLanguage)
        {
            Check.Require(validationLanguage, "validationLanguage");
            _validatorLanguage = validationLanguage;
        }

        /// <summary>
        /// Localize all error messages.
        /// </summary>
        /// <param name="errors">A list with validation errors.</param>
        /// <param name="modelLanguage"><see cref="LanguageNode"/> containing language strings for the validated model.</param>
        /// <returns>A list with localized errors; or an empty list if no validations failed.</returns>
        public NameValueCollection Localize(IEnumerable<ValidationError> errors, ILanguageNode modelLanguage)
        {
            NameValueCollection localizedErrors = new NameValueCollection();

            foreach (ValidationError error in errors)
            {
                localizedErrors.Add(error.Name,
                                    error.Attribute.Format(modelLanguage[error.Name], _validatorLanguage));
            }

            return localizedErrors;
        }

        /// <summary>
        /// Validates a model and returns errors in the current language.
        /// </summary>
        /// <remarks>
        /// Current language are decided by <see cref="CultureInfo.CurrentCulture"/>.
        /// </remarks>
        /// <param name="context">An application specific context that's passed to all validation attributes. Useful if you've implemented your own validations.</param>
        /// <param name="model">Model being validated.</param>
        /// <param name="language">Language node for the model.</param>
        /// <returns>A collection with all validations that failed; an empty collection if not validations failed.</returns>
        public NameValueCollection Validate(object context, object model, ILanguageNode language)
        {
            ObjectValidator validator = ObjectValidator.Create(model.GetType());
			if(validator == null)
				return new NameValueCollection();

            IList<ValidationError> validationErrors = validator.Validate(context, model);
            return Localize(validationErrors, language);
        }
    }
}
